package cn.yangliu.nacos.comm.handler.mvc;

import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.yangliu.nacos.comm.JsonResult;
import cn.yangliu.nacos.comm.handler.ResultAdvice;
import cn.yangliu.nacos.comm.handler.ResultConverter;
import cn.yangliu.nacos.comm.tools.JsonUtils;
import cn.yangliu.nacos.comm.tools.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * The type Global response body advice.
 *
 * <p>
 * .
 *
 * @author 问道于盲
 * @date 2019 -12-12
 */
@ControllerAdvice
@ConditionalOnClass(ResponseBodyAdvice.class)
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object>, ResultAdvice {

    /**
     * current class instance's member.
     * The Converter.
     */
    @Autowired(required = false)
    private ResultConverter converter;

    /**
     * Supports boolean.
     *
     * @param methodParameter the method parameter
     * @param aClass          the a class
     * @return the boolean
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        HttpServletRequest request = WebUtils.getRequest();
        assert request != null;
        String uri = request.getRequestURI();
        return ignore(uri);
    }

    /**
     * Before body write object.
     *
     * @param o                  the o
     * @param methodParameter    the method parameter
     * @param mediaType          the media type
     * @param aClass             the a class
     * @param serverHttpRequest  the server http request
     * @param serverHttpResponse the server http response
     * @return the object
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<?
            extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {

        HttpServletResponse response = WebUtils.getResponse();
        assert response != null;
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.setHeader("Content-Type", "application/json");

        if (Objects.nonNull(converter)) {
            Object result = converter.convert(o, serverHttpRequest, serverHttpResponse);
            if (Objects.nonNull(result)) {
                return result;
            }
        }

        if (o instanceof JsonResult) {
            return o;
        }

        if (o instanceof String) {
            return JsonUtils.objectToJson(JsonResult.getInstance(o));
        }

        return JsonResult.getInstance(o);
    }
}
